﻿namespace MicroCloud.Caching
{
    /// <summary>
    /// 表达式缓存键生成器
    /// </summary>
    public class ExpressionCacheKeyGenerator : ICacheKeyGenerator
    {
        //字段
        private readonly Expression _expression;

        /// <summary>
        /// 初始化一个表达式缓存键生成器 <see cref="ExpressionCacheKeyGenerator"/> 的新实例
        /// </summary>
        /// <param name="expression"></param>
        public ExpressionCacheKeyGenerator(Expression expression)
        {
            _expression = expression;
        }

        #region 方法 - Implementation of ICacheKeyGenerator
        /// <summary>
        /// 生成缓存键
        /// </summary>
        /// <param name="args">参数</param>
        /// <returns></returns>
        public string GetKey(params object[] args)
        {
            Expression expression = _expression;
            expression = Evaluator.PartialEval(expression, CanBeEvaluatedLocally);
            expression = LocalCollectionExpressionVisitor.Rewrite(expression);
            string key = expression.ToString();
            return key + args.ExpandAndToString();
        }

        #endregion

        #region 私有方法
        /// <summary>
        /// 可在本地评估
        /// </summary>
        /// <param name="expression"></param>
        /// <returns></returns>
        private static bool CanBeEvaluatedLocally(Expression expression)
        {
            if (expression.NodeType == ExpressionType.Parameter)
            {
                return false;
            }
            if (typeof(IQueryable).IsAssignableFrom(expression.Type))
            {
                return false;
            }
            return true;
        }

        #endregion
    }
}